package com.cs.framework.web.bind;

import java.util.Map;

import javax.servlet.ServletRequest;

import org.springframework.web.bind.ServletRequestDataBinder;

import com.cs.framework.common.util.JSONUtils;
import com.cs.framework.common.util.ReflectUtils;
import com.cs.framework.common.util.StringUtils;
import com.cs.framework.web.handler.Web;
import com.cs.framework.web.util.RequestUtils;

/**
 * 请求数据绑定器
 * 
 * @author hedongzhou
 *
 */
@SuppressWarnings("all")
public class RequestDataBinder {

	/**
	 * 获取参数
	 * 
	 * @param request
	 * @param param
	 * @return
	 */
	public static String getParameter(ServletRequest request, String param) {
		String contentType = request.getContentType();

		if (contentType == null || StringUtils.containsNone(contentType.toLowerCase(), "application/json")) {
			return request.getParameter(param);
		} else {
			try {
				return JSONUtils.toJsonNode(RequestUtils.getJSONString(request), param).asText();
			} catch (Exception e) {
				return null;
			}
		}
	}

	/**
	 * 获取参数
	 * 
	 * @param param
	 * @return
	 */
	public static String getParameter(String param) {
		return getParameter(Web.getRequest(), param);
	}

	/**
	 * 根据请求，绑定对象
	 * 
	 * @param request
	 * @param cls
	 *            目标对象类型
	 * @return
	 */
	public static <T> T bind(ServletRequest request, Class<T> cls) {
		String contentType = request.getContentType();

		if (contentType == null || StringUtils.containsNone(contentType.toLowerCase(), "application/json")) {
			return bindFromParam(request, cls);
		} else {
			return bindFromJson(request, cls);
		}
	}

	/**
	 * 根据请求，绑定对象
	 * 
	 * @param cls
	 *            目标对象类型
	 * @return
	 */
	public static <T> T bind(Class<T> cls) {
		return bind(Web.getRequest(), cls);
	}

	/**
	 * 把请求参数中的数据，绑定到目标对象上
	 * 
	 * @param request
	 * @param cls
	 *            目标对象类型
	 * @return
	 */
	public static <T> T bindFromParam(ServletRequest request, Class<T> cls) {
		if (ReflectUtils.isParent(cls, Map.class)) {
			return cls.cast(RequestUtils.getParameterMap(request));
		} else {
			T target = null;

			try {
				target = cls.newInstance();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}

			ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
			binder.setIgnoreInvalidFields(true);
			binder.setIgnoreUnknownFields(true);
			binder.bind(request);

			return target;
		}
	}

	/**
	 * 把请求参数中的数据，绑定到目标对象上
	 * 
	 * @param cls
	 *            目标对象类型
	 * @return
	 */
	public static <T> T bindFromParam(Class<T> cls) {
		return bind(Web.getRequest(), cls);
	}

	/**
	 * 把JSON数据绑定到目标对象上
	 * 
	 * @param request
	 * @param cls
	 *            目标对象类型
	 * @return
	 */
	public static <T> T bindFromJson(ServletRequest request, Class<T> cls) {
		return JSONUtils.toObject(RequestUtils.getJSONString(request), cls);
	}

	/**
	 * 把JSON数据绑定到目标对象上
	 * 
	 * @param cls
	 *            目标对象类型
	 * @return
	 */
	public static <T> T bindFromJson(Class<T> cls) {
		return bindFromJson(Web.getRequest(), cls);
	}

}
